package com.hyny.framework.platform.system.utils;


import cn.hutool.core.util.ClassUtil;
import com.hyny.framework.platform.system.annotation.FieldPower;
import com.hyny.framework.platform.system.entity.dto.FieldPowerDTO;
import com.hyny.framework.platform.system.entity.dto.LoginRoleFieldPowerDTO;
import com.hyny.framework.platform.system.utils.enums.FieldPowerTypeEnum;
import com.hyny.framework.utils.ClassEnhanceUtil;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.stream.Collectors;


/**
 * 获取字段权限工具类
 */
public class FieldPowerUtil {

    /**
     * 根据请求链接获取字段权限信息
     * @return
     */
    public  static List<LoginRoleFieldPowerDTO.Field> getFieldList(String req) {
        List<LoginRoleFieldPowerDTO> fieldPowerDTOs = SecurityUtil.getLoginUser().getFieldPowerDTOs();
        if (fieldPowerDTOs != null && fieldPowerDTOs.size() > 0) {
            if (fieldPowerDTOs != null && fieldPowerDTOs.size() > 0) {
                List<LoginRoleFieldPowerDTO.RequestUrl> requestUrls = fieldPowerDTOs.get(0).getRequestUrls()
                        .stream().filter(fil -> req.startsWith(fil.getRequestUrl()))
                        .collect(Collectors.toList());
                if (requestUrls != null && requestUrls.size() > 0) {
                    return requestUrls.get(0).getFields();
                }
            }
        }

        return null;
    }

    /**
     * 根据项目标识获取字段权限信息  仅字段名
     * @param reqUrl
     * @return
     */
    public static List<String> getFieldNameList(String reqUrl) {
        List<LoginRoleFieldPowerDTO.Field> fields= getFieldList(  reqUrl) ;
        List<String> fieldNames = fields.stream().map(e -> e.getFieldName()).collect(Collectors.toList()).stream().collect(Collectors.toList());
        return fieldNames;
    }


    /**
     * 根据请求类所在的包名获取请求类，获取请求方法的返回值字段
     * @param packageName 请求类所在的包名
     * @param permissions 权限标识
     * @return
     */
    public static List<FieldPowerDTO>  packageFieldPower(String packageName, String permissions){
        Set<Class<?>> classSetset= ClassEnhanceUtil.scanPackageByAnnotation(packageName, FieldPower.class);
        List<FieldPowerDTO> fieldPowerDTOS=new ArrayList<>();

        for (Class<?> cclass:classSetset
        ) {
            FieldPower classFieldPower=cclass.getAnnotation(FieldPower.class);
            FieldPowerDTO fieldPowerDTO=new FieldPowerDTO();
            fieldPowerDTO.setTitle(classFieldPower.value());
            fieldPowerDTO.setClassName(cclass.getSimpleName());
            fieldPowerDTO.setPosition(cclass.getName());
            fieldPowerDTO.setType(FieldPowerTypeEnum.CLASS);
            fieldPowerDTO.setPermissions((permissions+":"+cclass.getSimpleName()).toUpperCase(Locale.ROOT));
            fieldPowerDTO.setFieldPowerDTOList(classFieldPower(cclass,permissions));
            fieldPowerDTOS.add(fieldPowerDTO);
        }
        return fieldPowerDTOS;
    }


    /**
     * 根据请求类获取请求方法的返回值字段
     * @param cclass 请求类
     * @param permissions 权限标识
     * @return
     */
    public static List<FieldPowerDTO>  classFieldPower(Class<?> cclass, String permissions){
        List<FieldPowerDTO> fieldPowerDTOS=new ArrayList<>();
        //获取包含FieldPower注解的全部方法
        List<Method> methods= ClassEnhanceUtil.getMethodsDirectlyAnnotation(cclass, FieldPower.class);
        //遍历controller中方法
        for (Method method: methods) {
            FieldPower fieldFieldPower=method.getAnnotation(FieldPower.class);
            if(fieldFieldPower!=null){
                FieldPowerDTO fieldPowerDTO=new FieldPowerDTO();
                fieldPowerDTO.setTitle(fieldFieldPower.value());
                fieldPowerDTO.setClassName(cclass.getSimpleName());
                fieldPowerDTO.setMethodName(method.getName());
                fieldPowerDTO.setPosition(cclass.getName()+ "." +method.getName());
                fieldPowerDTO.setType(FieldPowerTypeEnum.METHOD);
                fieldPowerDTO.setPermissions((permissions+":"+cclass.getSimpleName()+":"+method.getName()).toUpperCase(Locale.ROOT));
                fieldPowerDTO.setFieldPowerDTOList(methodFieldPower(cclass,method,permissions));
                fieldPowerDTOS.add(fieldPowerDTO);
            }
        }
        return fieldPowerDTOS;
    }


    /**
     * 根据方法获取返回值字段
     * @param cclass 请求类
     * @param method 请求方法
     * @param permissions 权限标识
     * @return
     */
    public static List<FieldPowerDTO> methodFieldPower(Class<?> cclass, Method method, String permissions){
        List<FieldPowerDTO> fieldPowerDTOS=new ArrayList<>();
        //获取方法注解
        FieldPower methodFieldPower=method.getAnnotation(FieldPower.class);
        //根据注解获取返回值类型
        Class<?> returnType=methodFieldPower.returnType();
        //根据返回值类型获取当前返回值下所有的属性
        Field[]  fields= ClassUtil.getDeclaredFields(returnType);
        for (Field field: fields
        ) {
            FieldPower fieldFieldPower=field.getAnnotation(FieldPower.class);
            if(fieldFieldPower!=null){
                FieldPowerDTO fieldPowerDTO=new FieldPowerDTO();
                fieldPowerDTO.setTitle(fieldFieldPower.value());
                fieldPowerDTO.setClassName(cclass.getSimpleName());
                fieldPowerDTO.setMethodName(method.getName());
                fieldPowerDTO.setPosition(cclass.getName()+ "." +method.getName());
                fieldPowerDTO.setFieldName(field.getName());
                fieldPowerDTO.setType(FieldPowerTypeEnum.FIELD);
                fieldPowerDTO.setPermissions((permissions+":"+cclass.getSimpleName()+":"+method.getName()+":"+field.getName()).toUpperCase(Locale.ROOT));
                fieldPowerDTOS.add(fieldPowerDTO);
            }
        }

        return fieldPowerDTOS;

    }
}
